package model

import (
	"encoding/json"
	"io/ioutil"
	"log"
	"net"
	"os"
	"strings"
	"time"
)

var (
	Sleep       time.Duration = 3 //客户端UDP请求间隔时间
	OffOlineMac               = make(map[string]map[string]map[string]string)
	client      *net.UDPConn
	err         error
)

func init() {
	if fileObj, err := os.Open("./Mac.cache"); err == nil {
		defer fileObj.Close()
		if contents, err := ioutil.ReadAll(fileObj); err == nil {
			if len(contents) > 0 {
				result := strings.Replace(string(contents), "\n", "", 1)
				err := json.Unmarshal([]byte(result), &Mac)
				if err != nil {
					log.Fatal("JsonToMap err: ", err)
				}
				wg.Lock()
				for k, _ := range Mac {
					Mac[k]["overtime"] = int64(Mac[k]["overtime"].(float64))
					Mac[k]["time"] = int64(Mac[k]["time"].(float64))
					Mac[k]["OffOnline"] = int(Mac[k]["OffOnline"].(float64))
					Mac[k]["FailNum"] = int64(Mac[k]["FailNum"].(float64))
				}
				wg.Unlock()
			}
		}
	}
}

//udp服务端 监听广播
func Udpserver() {
	server, _ := net.ListenPacket("udp", ":"+UdpPort)
	buff := make([]byte, 81920)
	for {
		count, _addr, _ := server.ReadFrom(buff)
		ip := _addr.String()
		ip = ip[:strings.Index(ip, ":")]
		MacInfo := MacInfo{}

		if err := json.Unmarshal(buff[0:count], &MacInfo); err == nil {
			wg.Lock()
			if MacInfo.TYPE == 1 {
				Mac = make(map[string]map[string]interface{})               //清空内存中的设备
				OffOlineMac = make(map[string]map[string]map[string]string) //清空内存中的离线设备
				os.Truncate("log_info.log", 0)                              //清空错误日志
				os.Truncate("Mac.cache", 0)                                 //清空设备日志
				os.Truncate("OffOnline.log", 0)                             //清空线设备日志
			} else {
				for k, v := range MacInfo.OffOlineLog { //key 问题机器 val 检测机器
					_kk := ""
					_vv := make(map[string]string)
					for kk, vv := range v {
						_kk = kk
						_vv = vv
					}

					if OffOlineMac[k] == nil {
						OffOlineMac[k] = make(map[string]map[string]string)
					}

					if OffOlineMac[k][_kk] == nil {
						OffOlineMac[k][_kk] = make(map[string]string)
					}

					OffOlineMac[k][_kk] = _vv
				}

				MacInfo.OffOlineLog = make(map[string]map[string]map[string]string)

				if _, ok := Mac[ip]["FailNum"]; !ok {
					Mac[ip] = make(map[string]interface{})
					Mac[ip]["FailNum"] = int64(0)
					Mac[ip]["testSpeed"] = "未测试"
					Mac[ip]["testPort"] = "未测试"
				}
				Mac[ip]["ip"] = ip
				Mac[ip]["Network"] = _addr.Network()
				Mac[ip]["time"] = time.Now().Unix()
				Mac[ip]["timeFormat"] = MacInfo.STIME.Format("2006-01-02 15:04:05")
				Mac[ip]["overtime"] = time.Now().Unix() + (int64(Sleep) + 5) //过期时间戳
				Mac[ip]["MacInfo"] = MacInfo
				Mac[ip]["OffOnline"] = 0                             //离线状态
				Mac[ip]["cost"] = time.Since(MacInfo.STIME).String() //耗时
				Mac[ip]["isSelf"] = "0"                              //是否是本机
				if IntranetIp == ip {
					Mac[ip]["isSelf"] = "1"
				}
			}
			wg.Unlock()
		}
	}
}

//客户端 定时发送广播 证明自己存活
func Udpclient() {
	radd, _ := net.ResolveUDPAddr("udp", "255.255.255.255:"+UdpPort)
	client, err = net.DialUDP("udp", nil, radd)
	if err != nil {
		Log.Println("DialUDP Err:", err.Error())
		panic(err)
	} else {
		//client.SetDeadline(time.Now().Add(time.Second * 3))
		ticker := time.NewTicker(time.Second * Sleep)
		go func() {
			for _ = range ticker.C {
				MacInfo := CreateMacInfo()
				MacInfo.STIME = time.Now()
				JsonMacInfo, _ := json.Marshal(MacInfo)
				if _, err := client.Write(JsonMacInfo); err != nil {
					Log.Println("client.Write Err:", err.Error())
					panic(err)
				}
			}
		}()
	}
}
